
//--------------------------------------------------------------------------------------
// Constant Buffer Variables
//--------------------------------------------------------------------------------------
matrix Model;
matrix View;
matrix Projection;
float rHalo;
float tHalo;


Texture2D HaloGradient;
Texture2D Noise;
Texture2D IntermediateTargetHalo;
Texture2D IntermediateTargetSphereBack;
Texture2D IntermediateTargetSphereFront;

SamplerState samLinear
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

SamplerState samLinearClamp
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Clamp;
    AddressV = Clamp;
};

BlendState NoBlending
{
    BlendEnable[0] = FALSE;
};

//--------------------------------------------------------------------------------------
// PASS 0 - Halo
//--------------------------------------------------------------------------------------
struct VS_OUTPUT
{
    float4 Pos : SV_POSITION;
    float2 Tex : TEXCOORD;
};

// Vertex Shader P0
VS_OUTPUT VS0( float4 Pos : POSITION, 
                float3 Tex : TEXCOORD
                 )
{
    VS_OUTPUT output = (VS_OUTPUT)0;
    
    output.Pos = Pos;
    output.Tex = Pos.xy;
    return output;
}


// Pixel Shader P0
float4 PS0( VS_OUTPUT input ) : SV_Target
{
    float r = sqrt( dot(input.Tex, input.Tex) );
    float t = atan2(input.Tex.x, input.Tex.y) / (0.5 * 3.1415);
    float2 noiseOffset = (0.3 * r + tHalo) * Noise.Sample( samLinear, float2(r - rHalo,t)).xy;
    return float4(HaloGradient.Sample( samLinearClamp, float2(r + noiseOffset.x, 0)).xyz, 1);
}

//--------------------------------------------------------------------------------------
// PASS 1 - Sphere Back
//--------------------------------------------------------------------------------------
struct VS_OUTPUT1
{
    float4 Pos : SV_POSITION;
    float3 Nor : NORMAL;
    float2 Tex : TEXCOORD;
};

// Vertex Shader P1
VS_OUTPUT1 VS1( float4 Pos : POSITION, 
                float3 Normal : NORMAL
                 )
{
    VS_OUTPUT1 output = (VS_OUTPUT1)0;
    
    output.Pos = mul(Pos, Model);
    output.Pos = mul(output.Pos, View);
    output.Pos = mul(output.Pos, Projection);
    output.Nor = mul(float4(Normal,0), Model);
    output.Tex = output.Pos * 0.125 + 0.5;
    return output;
}


// Pixel Shader P1
float4 PS1( VS_OUTPUT1 input ) : SV_Target
{
    float2 Tex = input.Tex + 0.1 *input.Nor.xy;
    float4 color1 = IntermediateTargetHalo.Sample( samLinearClamp, Tex);
    return color1;
}

RasterizerState RsBack{
    CullMode = Front;
};

//--------------------------------------------------------------------------------------
// PASS 2 - Sphere Front
//--------------------------------------------------------------------------------------
// Pixel Shader P2
float3 PS2( VS_OUTPUT1 input ) : SV_Target
{
    float2 Tex = input.Tex - 0.1 *input.Nor.xy;
    float3 color1 = IntermediateTargetSphereBack.Sample( samLinearClamp, Tex);
    return color1;
}

RasterizerState RsFront{
    CullMode = Back;
};


//--------------------------------------------------------------------------------------
// PASS 3 - Final
//--------------------------------------------------------------------------------------

// Vertex Shader P3
VS_OUTPUT VS3( float4 Pos : POSITION, 
                float2 Tex : TEXCOORD
                 )
{
    VS_OUTPUT output = (VS_OUTPUT)0;
    output.Pos = Pos;
    output.Tex = Tex;
    return output;
}


// Pixel Shader P3
float4 PS3( VS_OUTPUT input ) : SV_Target
{
    float4 color0 = IntermediateTargetHalo.Sample( samLinear, input.Tex);
    float4 color1 = IntermediateTargetSphereBack.Sample( samLinear, input.Tex);
    float4 color2 = IntermediateTargetSphereFront.Sample( samLinear, input.Tex);
    float4 color = (1 - color1.w) * color0 + color1.w * color1;
    color =  (1 - color2.w) * color + color2.w * color2;
    return color;
}



//--------------------------------------------------------------------------------------
technique10 Render
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS0() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS0() ) );
        SetRasterizerState( RsFront );
        SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    }

    pass P1
    {
        SetVertexShader( CompileShader( vs_4_0, VS1() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS1() ) );
        SetRasterizerState( RsBack );
        SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    }

    pass P2
    {
        SetVertexShader( CompileShader( vs_4_0, VS1() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS2() ) );
        SetRasterizerState( RsFront );
        SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    }

    pass P3
    {
        SetVertexShader( CompileShader( vs_4_0, VS3() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS3() ) );
        SetRasterizerState( RsFront );
        SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    }

}

